Una vez descargados los archivos de datos, vamos a ubicarlos al interior de una carpeta llamada data que a su vez crearemos dentro del directorio de nuestro proyecto.
# Instalamos los paquetes
install.packages("tidyverse", dependencies=TRUE, INSTALL_opts = c("--no-multiarch"))
install.packages("readxl")
install.packages("haven")
install.packages("googlesheets4")
install.packages("DBI")
install.packages("RMySQL")
# Cargamos los paquetes
library("tidyverse")
library("readxl")
library("haven")
library("googlesheets4")
library("DBI")
library("RMySQL")Podemos leer desde R hojas de cálculo públicas o privadas.
# library("googlesheets4")
# Comando para que no nos exija autenticación
gs4_deauth()
# Declaro el enlace
link = "https://docs.google.com/spreadsheets/d/1z7uEedjNKXN4ub5lNZLO-dJhtWs4-Lv3PRcOTf-HWdk/edit?usp=sharing"
# Lectura de datos
boston_housing_gs <- read_sheet(link)
str(boston_housing_gs)Ya sabemos importar datos.
Ahora vamos a ver distintos elementos que necesitamos para procesarlos.
Un algoritmo es un conjunto finito de instrucciones que, si se siguen rigurosamente, llevan a cabo una tarea específica.
Todos los algoritmos se componen de “partes” básicas que se utilizan para crear “partes” más complejas.
El tratamiento, análisis y modelado de datos lo haremos mediante algoritmos.
## [1] TRUE
## [1] "logical"
## [1] TRUE
## [1] 3.141593
## [1] 0
## [1] "numeric"
## [1] TRUE
## [1] "hola mundo"
## [1] "character"
## [1] TRUE
## [1] "2022-03-24"
## [1] "character"
## [1] "Date"
## [1] NA
## [1] "logical"
## [1] TRUE
## [1] FALSE
## [1] FALSE
## [1] TRUE
## [1] "logical"
## [1] "TRUE"
## [1] "character"
## [1] 1
## [1] "numeric"
## [1] "1"
## [1] "character"
| Desde | Hacia |
|---|---|
| logical | numeric |
| logical | character |
| numeric | character |
| numeric | Date |
| character | Date |
## [1] 4
## [1] 3
## [1] 12
## [1] 1.25
## [1] 1
## [1] 27
## [1] 27
## [1] 2.302585
## [1] 4
## [1] TRUE
## [1] FALSE
## [1] TRUE
## [1] FALSE
## [1] TRUE
## [1] TRUE
## [1] FALSE
## [1] 28.2735
## [1] 28.27
Son vectores numéricos enmascarados como caracteres. Se usan para crear grupos usando clasificaciones o codificaciones de las variables de interés. Estos factores pueden o no tener un orden.
Ejemplos: estrato socioeconómico, nivel de estudios, mes, sexo, localidad.
## [1] 1 2 3 4 5
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
## [20] "T" "U" "V" "W" "X" "Y" "Z"
## [1] 1 3 2 15 4 0 0 0 1
## [1] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
## [20] 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
## [39] 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
## [58] 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
## [77] 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
## [1] 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
## [1] 10.00000 22.85714 35.71429 48.57143 61.42857 74.28571 87.14286
## [8] 100.00000
## [1] a b c d e f g h i j k l m n o p q r s t u v w x y z
## Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z
vector_logico <- c(TRUE,FALSE,FALSE,TRUE,FALSE)
vector_cualquiera <- seq(1, 100, by = 3)
un_vector <- c(1, 2, 3, 4, 5)
otro_vector <- c(6, 7, 8, 9, 10)## [1] 1 4
## [1] 34
## [1] 1 2 3 4 5 6 7 8 9 10
## [1] FALSE TRUE TRUE TRUE TRUE
## [1] FALSE FALSE TRUE TRUE TRUE
## [,1] [,2] [,3]
## [1,] 3 4 5
## [2,] 6 8 10
## [3,] 9 12 15
## [,1] [,2] [,3]
## [1,] FALSE FALSE FALSE
## [2,] FALSE FALSE FALSE
## [3,] FALSE FALSE FALSE
## [1] 1 2 3 4 5
## [1] 3
## [1] 1 2
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
## [,1] [,2]
## [1,] 1 7
## [2,] 2 8
## [3,] 3 9
## [4,] 4 10
## [5,] 5 11
## [6,] 6 12
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 3 5 7 9 11
## [2,] 2 4 6 8 10 12
## [,1] [,2] [,3]
## [1,] 1 5 9
## [2,] 2 6 10
## [3,] 3 7 11
## [4,] 4 8 12
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
## [4,] 10 11 12
## [,1] [,2]
## [1,] 0 6
## [2,] 3 9
## [,1] [,2]
## [1,] 0 3
## [2,] 6 9
## [1] 0 9
## [1] -18
solve(mi_matriz) # Matriz inversa, sólo se puede con matrices cuadradas de determinante distinto de cero## [,1] [,2]
## [1,] -0.5000000 0.3333333
## [2,] 0.1666667 0.0000000
## [1] 2 2
Bibliografía complementaria: Capítulo 2: Linear Algebra, del libro Deep Learning del MIT
## [1] "a" "h" "f" "c"
## [1] 4 6 8 10
## [1] 1
## [1] 6
## [1] 0 3
## [1] 3 9
## # A tibble: 53,940 × 1
## x
## <dbl>
## 1 3.95
## 2 3.89
## 3 4.05
## 4 4.2
## 5 4.34
## 6 3.94
## 7 3.95
## 8 4.07
## 9 3.87
## 10 4
## # ℹ 53,930 more rows
## # A tibble: 53,940 × 1
## x
## <dbl>
## 1 3.95
## 2 3.89
## 3 4.05
## 4 4.2
## 5 4.34
## 6 3.94
## 7 3.95
## 8 4.07
## 9 3.87
## 10 4
## # ℹ 53,930 more rows
cuales_extraer = c("x","y","z") # Creo un vector de variables a extraer
diamonds[cuales_extraer] #Hago la extracción## # A tibble: 53,940 × 3
## x y z
## <dbl> <dbl> <dbl>
## 1 3.95 3.98 2.43
## 2 3.89 3.84 2.31
## 3 4.05 4.07 2.31
## 4 4.2 4.23 2.63
## 5 4.34 4.35 2.75
## 6 3.94 3.96 2.48
## 7 3.95 3.98 2.47
## 8 4.07 4.11 2.53
## 9 3.87 3.78 2.49
## 10 4 4.05 2.39
## # ℹ 53,930 more rows
Ejemplo
A partir de la base de datos de Boston, hagamos una prueba de hipótesis para testear si el valor medio de la vivienda (variable MEDV) está influenciado/afectado por el hecho que la vivienda limite con el río Charles River (variable dummy CHAS).
##
## Welch Two Sample t-test
##
## data: MEDV by CHAS
## t = -3.1133, df = 36.876, p-value = 0.003567
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
## -10.476831 -2.215483
## sample estimates:
## mean in group 0 mean in group 1
## 22.09384 28.44000
¿Qué podríamos extraer de este objeto?
## List of 10
## $ statistic : Named num -3.11
## ..- attr(*, "names")= chr "t"
## $ parameter : Named num 36.9
## ..- attr(*, "names")= chr "df"
## $ p.value : num 0.00357
## $ conf.int : num [1:2] -10.48 -2.22
## ..- attr(*, "conf.level")= num 0.95
## $ estimate : Named num [1:2] 22.1 28.4
## ..- attr(*, "names")= chr [1:2] "mean in group 0" "mean in group 1"
## $ null.value : Named num 0
## ..- attr(*, "names")= chr "difference in means between group 0 and group 1"
## $ stderr : num 2.04
## $ alternative: chr "two.sided"
## $ method : chr "Welch Two Sample t-test"
## $ data.name : chr "MEDV by CHAS"
## - attr(*, "class")= chr "htest"
Extraigamos, por ejemplo, el p-valor de la prueba.
## $p.value
## [1] 0.00356717
## [1] 0.00356717
## [1] 0.00356717
Podemos extraer partes de todos los objetos que tengamos en nuestro ambiente de trabajo.
Otro ejemplo
Ajustemos un modelo de regresión lineal simple usando como variable respuesta el valor medio de la vivienda (variable MEDV) en función del número medio de habitaciones de la vivienda (variable RM).
##
## Call:
## lm(formula = MEDV ~ RM, data = boston_housing_xlsx)
##
## Coefficients:
## (Intercept) RM
## -34.671 9.102
##
## Call:
## lm(formula = MEDV ~ RM, data = boston_housing_xlsx)
##
## Residuals:
## Min 1Q Median 3Q Max
## -23.346 -2.547 0.090 2.986 39.433
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -34.671 2.650 -13.08 <2e-16 ***
## RM 9.102 0.419 21.72 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 6.616 on 504 degrees of freedom
## Multiple R-squared: 0.4835, Adjusted R-squared: 0.4825
## F-statistic: 471.8 on 1 and 504 DF, p-value: < 2.2e-16
¿Qué podríamos extraer de este objeto?
## List of 11
## $ call : language lm(formula = MEDV ~ RM, data = boston_housing_xlsx)
## $ terms :Classes 'terms', 'formula' language MEDV ~ RM
## .. ..- attr(*, "variables")= language list(MEDV, RM)
## .. ..- attr(*, "factors")= int [1:2, 1] 0 1
## .. .. ..- attr(*, "dimnames")=List of 2
## .. .. .. ..$ : chr [1:2] "MEDV" "RM"
## .. .. .. ..$ : chr "RM"
## .. ..- attr(*, "term.labels")= chr "RM"
## .. ..- attr(*, "order")= int 1
## .. ..- attr(*, "intercept")= int 1
## .. ..- attr(*, "response")= int 1
## .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
## .. ..- attr(*, "predvars")= language list(MEDV, RM)
## .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
## .. .. ..- attr(*, "names")= chr [1:2] "MEDV" "RM"
## $ residuals : Named num [1:506] -1.18 -2.17 3.97 4.37 5.82 ...
## ..- attr(*, "names")= chr [1:506] "1" "2" "3" "4" ...
## $ coefficients : num [1:2, 1:4] -34.671 9.102 2.65 0.419 -13.084 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:2] "(Intercept)" "RM"
## .. ..$ : chr [1:4] "Estimate" "Std. Error" "t value" "Pr(>|t|)"
## $ aliased : Named logi [1:2] FALSE FALSE
## ..- attr(*, "names")= chr [1:2] "(Intercept)" "RM"
## $ sigma : num 6.62
## $ df : int [1:3] 2 504 2
## $ r.squared : num 0.484
## $ adj.r.squared: num 0.483
## $ fstatistic : Named num [1:3] 472 1 504
## ..- attr(*, "names")= chr [1:3] "value" "numdf" "dendf"
## $ cov.unscaled : num [1:2, 1:2] 0.1604 -0.02521 -0.02521 0.00401
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:2] "(Intercept)" "RM"
## .. ..$ : chr [1:2] "(Intercept)" "RM"
## - attr(*, "class")= chr "summary.lm"
Extraigamos el \(R^2\) ajustado del modelo.
## [1] 0.4825007
El control flow es un conjunto de funciones que permiten manejar las órdenes de manera estructurada y lógica. Las más importantes son:
Todos los lenguajes modernos de programación ofrecen una o más maneras de realizar operaciones iterativas. El poder repetir la misma acción una cantidad indefinida de veces es una de las grandes ventajas de realizar las tareas mediante programación.
for
Sirve para crear tareas repetitivas de un número de pasos específico.
Uno de los usos más frecuentes de un ciclo for es la configuración de métodos de remuestreo (bootstraping).
#vamos a guardar en una lista los coeficientes de una regresión
coeficientes <- list()
# inicializo el ciclo for
for(i in 1:1000){
#en cada paso
# 1. saco una muestra de 100 casas
muestra <- sample_n(boston_housing_xlsx, 100)
# 2. ajusto un modelo de regresión lineal
lm(MEDV ~ RM, data = muestra) -> modelo
# 3. extraigo y almaceno los coeficientes del modelo
coeficientes[[i]] <- coefficients(modelo)
}
# grafico el comportamiento de los coeficientes
coeficientes %>%
transpose %>%
lapply(unlist) %>%
as_tibble() %>%
gather(key = coeficiente, value = valor) %>%
ggplot +
aes(x = valor) +
geom_density() +
facet_wrap(~coeficiente, nrow = 2, scales = "free")while
Sirve para crear tareas repetitivas que no sabemos después de cuántos pasos terminan. Requiere una inicialización cuidadosa.
Ejemplo: ¿Cuántos sobres tengo que comprar para llenar un álbum de 100 cromos?
# inicializo las condiciones de partida
album <- iteracion <- 0
# creo la condición lógica que permite ejecutar el proceso
aun_falta <- TRUE
# siempre que aun_falta siga siendo verdadero
while(aun_falta){
# en cada ciclo
# 1. actualizo en qué iteración voy
iteracion <- iteracion + 1
# 2. extraigo una muestra de 6 números ("compro un sobre con 6 cromos")
sobre <- sample(100, 6)
# 3.1 tomo el álbum
# 3.2 le combino los cromos que obtuve
# 3.3 ordeno los cromos de menor a mayor
# 3.4 dejo valores únicos (quito cromos duplicados)
# 3.5 actualizo el álbum
album %>% c(sobre) %>% sort %>% unique -> album
# 4. si tengo menos de 100 cromos es porque me falta
length(album) < 100 -> aun_falta
}
# muestro el número de iteraciones
# es decir, cuántos sobres tuve que comprar
iteracion## [1] 82
La estructura if sirve para ejecutar varias rutinas distintas dependiendo de una condición lógica. En caso de que sea necesario, es posible aplicar una rutina alterna con la estructura else.
Ejemplo: Prueba de normalidad.
Diversas pruebas y modelos estadísticos requieren verificar el supuesto de normalidad en los datos.
# de la base de datos de carros
# extraigo la variable mpg
# le hago un test de shapiro
# guardo los resultados de la prueba en un objeto llamado prueba_sw
mtcars[["mpg"]] %>% shapiro.test() -> prueba_sw
# estructura condicional
if(prueba_sw$p.value > 0.05){
# Si acepto la hipótesis de normalidad en la variable mpg
# Hago una prueba t
print("La variable mpg sigue una distribución normal")
print("Realizo una prueba t")
t.test(mpg ~ vs, data = mtcars)
} else {
# Si rechazo la hipótesis de normalidad en la variable mpg
# Hago una prueba Mann-Whitney-Wilcoxon
print("La variable mpg no sigue una distribución normal")
print("Realizo una prueba Mann-Whitney-Wilcoxon")
wilcox.test(mpg ~ vs, data = mtcars)
}## [1] "La variable mpg sigue una distribución normal"
## [1] "Realizo una prueba t"
##
## Welch Two Sample t-test
##
## data: mpg by vs
## t = -4.6671, df = 22.716, p-value = 0.0001098
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
## -11.462508 -4.418445
## sample estimates:
## mean in group 0 mean in group 1
## 16.61667 24.55714